1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.math;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.math.MathPreconditions.checkNonNegative;
22 import static com.google.common.math.MathPreconditions.checkPositive;
23 import static com.google.common.math.MathPreconditions.checkRoundingUnnecessary;
24 import static java.math.RoundingMode.CEILING;
25 import static java.math.RoundingMode.FLOOR;
26 import static java.math.RoundingMode.HALF_EVEN;
27
28 import com.google.common.annotations.GwtCompatible;
29 import com.google.common.annotations.VisibleForTesting;
30
31 import java.math.BigInteger;
32 import java.math.RoundingMode;
33 import java.util.ArrayList;
34 import java.util.List;
35
36
37
38
39
40
41
42
43
44
45
46
47
48 @GwtCompatible(emulated = true)
49 public final class BigIntegerMath {
50
51
52
53 public static boolean isPowerOfTwo(BigInteger x) {
54 checkNotNull(x);
55 return x.signum() > 0 && x.getLowestSetBit() == x.bitLength() - 1;
56 }
57
58
59
60
61
62
63
64
65 @SuppressWarnings("fallthrough")
66
67 public static int log2(BigInteger x, RoundingMode mode) {
68 checkPositive("x", checkNotNull(x));
69 int logFloor = x.bitLength() - 1;
70 switch (mode) {
71 case UNNECESSARY:
72 checkRoundingUnnecessary(isPowerOfTwo(x));
73 case DOWN:
74 case FLOOR:
75 return logFloor;
76
77 case UP:
78 case CEILING:
79 return isPowerOfTwo(x) ? logFloor : logFloor + 1;
80
81 case HALF_DOWN:
82 case HALF_UP:
83 case HALF_EVEN:
84 if (logFloor < SQRT2_PRECOMPUTE_THRESHOLD) {
85 BigInteger halfPower = SQRT2_PRECOMPUTED_BITS.shiftRight(
86 SQRT2_PRECOMPUTE_THRESHOLD - logFloor);
87 if (x.compareTo(halfPower) <= 0) {
88 return logFloor;
89 } else {
90 return logFloor + 1;
91 }
92 }
93
94
95
96
97
98
99 BigInteger x2 = x.pow(2);
100 int logX2Floor = x2.bitLength() - 1;
101 return (logX2Floor < 2 * logFloor + 1) ? logFloor : logFloor + 1;
102
103 default:
104 throw new AssertionError();
105 }
106 }
107
108
109
110
111
112
113 @VisibleForTesting static final int SQRT2_PRECOMPUTE_THRESHOLD = 256;
114
115 @VisibleForTesting static final BigInteger SQRT2_PRECOMPUTED_BITS =
116 new BigInteger("16a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a", 16);
117
118 private static final double LN_10 = Math.log(10);
119 private static final double LN_2 = Math.log(2);
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public static BigInteger factorial(int n) {
134 checkNonNegative("n", n);
135
136
137 if (n < LongMath.factorials.length) {
138 return BigInteger.valueOf(LongMath.factorials[n]);
139 }
140
141
142 int approxSize = IntMath.divide(n * IntMath.log2(n, CEILING), Long.SIZE, CEILING);
143 ArrayList<BigInteger> bignums = new ArrayList<BigInteger>(approxSize);
144
145
146 int startingNumber = LongMath.factorials.length;
147 long product = LongMath.factorials[startingNumber - 1];
148
149 int shift = Long.numberOfTrailingZeros(product);
150 product >>= shift;
151
152
153 int productBits = LongMath.log2(product, FLOOR) + 1;
154 int bits = LongMath.log2(startingNumber, FLOOR) + 1;
155
156 int nextPowerOfTwo = 1 << (bits - 1);
157
158
159 for (long num = startingNumber; num <= n; num++) {
160
161 if ((num & nextPowerOfTwo) != 0) {
162 nextPowerOfTwo <<= 1;
163 bits++;
164 }
165
166 int tz = Long.numberOfTrailingZeros(num);
167 long normalizedNum = num >> tz;
168 shift += tz;
169
170 int normalizedBits = bits - tz;
171
172 if (normalizedBits + productBits >= Long.SIZE) {
173 bignums.add(BigInteger.valueOf(product));
174 product = 1;
175 productBits = 0;
176 }
177 product *= normalizedNum;
178 productBits = LongMath.log2(product, FLOOR) + 1;
179 }
180
181 if (product > 1) {
182 bignums.add(BigInteger.valueOf(product));
183 }
184
185 return listProduct(bignums).shiftLeft(shift);
186 }
187
188 static BigInteger listProduct(List<BigInteger> nums) {
189 return listProduct(nums, 0, nums.size());
190 }
191
192 static BigInteger listProduct(List<BigInteger> nums, int start, int end) {
193 switch (end - start) {
194 case 0:
195 return BigInteger.ONE;
196 case 1:
197 return nums.get(start);
198 case 2:
199 return nums.get(start).multiply(nums.get(start + 1));
200 case 3:
201 return nums.get(start).multiply(nums.get(start + 1)).multiply(nums.get(start + 2));
202 default:
203
204 int m = (end + start) >>> 1;
205 return listProduct(nums, start, m).multiply(listProduct(nums, m, end));
206 }
207 }
208
209
210
211
212
213
214
215
216
217 public static BigInteger binomial(int n, int k) {
218 checkNonNegative("n", n);
219 checkNonNegative("k", k);
220 checkArgument(k <= n, "k (%s) > n (%s)", k, n);
221 if (k > (n >> 1)) {
222 k = n - k;
223 }
224 if (k < LongMath.biggestBinomials.length && n <= LongMath.biggestBinomials[k]) {
225 return BigInteger.valueOf(LongMath.binomial(n, k));
226 }
227
228 BigInteger accum = BigInteger.ONE;
229
230 long numeratorAccum = n;
231 long denominatorAccum = 1;
232
233 int bits = LongMath.log2(n, RoundingMode.CEILING);
234
235 int numeratorBits = bits;
236
237 for (int i = 1; i < k; i++) {
238 int p = n - i;
239 int q = i + 1;
240
241
242
243 if (numeratorBits + bits >= Long.SIZE - 1) {
244
245
246 accum = accum
247 .multiply(BigInteger.valueOf(numeratorAccum))
248 .divide(BigInteger.valueOf(denominatorAccum));
249 numeratorAccum = p;
250 denominatorAccum = q;
251 numeratorBits = bits;
252 } else {
253
254 numeratorAccum *= p;
255 denominatorAccum *= q;
256 numeratorBits += bits;
257 }
258 }
259 return accum
260 .multiply(BigInteger.valueOf(numeratorAccum))
261 .divide(BigInteger.valueOf(denominatorAccum));
262 }
263
264
265
266 private BigIntegerMath() {}
267 }
268